package com.practice.service;
import com.alibaba.fastjson2.JSON;
import com.practice.entity.Department;
import com.practice.mapper.DepartmentMapper;
import javafx.scene.paint.Stop;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StopWatch;

import java.util.*;
import java.util.stream.Collectors;
/**
 * @program: tenghw-practice-demo
 * @author: tenghw
 * @create: 2024-01-19 01:37
 * @Version 1.0
 * @description:
 **/
@Slf4j
@Service
public class DepartmentService {
    @Autowired
    DepartmentMapper departmentMapper;
    public List<Department> findAll(){
        List<Department> departmentList = departmentMapper.findAll();
        return departmentList;
    }
    public  List<Department> getDepartmentById(Integer id){
        List<Department> departmentListById = departmentMapper.getDepartmentById(id);
        return departmentListById;
    }
    /**
     * 查询部门和其所有子节点部门
     * @param list 要递归的集合
     * @param id id指定递归的部门的id
     * @return String树形结构
     * @throws Exception
     * @description: 使用嵌套for循环，遍历list中的数据，将数据与list中的数据比对，将比对结果加入到list中
    * */
    public String  recursionDepartment1(List<Department> list,Integer id) throws InterruptedException {
        StopWatch stopWatch=new StopWatch();
        log.warn("Route=>DepartmentService method=recursionDepartment1 要递归的数据list为：{}",list);
        if(CollectionUtils.isEmpty(list)){
           log.error("lRoute=>DepartmentService method=recursionDepartment1 要递归的数据list集合为空！");
           return "[]";
       }
        stopWatch.start("recursionDepartment1");
       // 2层嵌套循环，即取出list中每一条数据，该数据再和list中每一条数据比对
        for(Department department : list){
            // 检查department为null，终止本次循环
            if (department == null) {
                continue;
            }
            for(Department department1 : list){
                // 检查department1为null，终止本次循环
                if (department1 == null) {
                    continue;
                }
                if(department1.getParentId()==department.getId()){//如果department1有父节点，把department1挂到其父节department点下
                    if(Objects.isNull(department.getChildren())){
                        department.setChildren(new ArrayList<>());//一个父节点添加第一个子节点前，先初始化setChildren(List)
                    }
                    department1.setChildren(new ArrayList<>());
                    department.getChildren().add(department1);
                }
            }
        }
        // 获取所有根节点（即没有父节点的部门），因为上面2层for循环已经把有父节点的数据挂到其父节点下，所有根节点不止根节点，还有其所有的子节点（包括子节点的子节点）
        List<Department> rootDepartments;
        if(id==null){
            log.info("Route=>DepartmentService method=recursionDepartment1 查询所有部门的树形结构");
             rootDepartments  = list.stream().filter(department -> department.getParentId() == 0)
                    .sorted(Comparator.comparing(Department::getId))//树结构根据id排序（默认升序）
                    .collect(Collectors.toList());
        }else{
            log.info("Route=>DepartmentService method=recursionDepartment1 查询指定部门及其子节点部门的树形结构");
            rootDepartments  = list.stream().filter(department -> department.getId() == id)
                    .sorted(Comparator.comparing(Department::getId).reversed())//树结构根据id排序（降序）
                    .collect(Collectors.toList());
        }
        Thread.sleep(1000);
        stopWatch.stop();
        System.out.println("本方法耗时：" + stopWatch.getLastTaskTimeMillis());
        System.out.println("总耗时：" + stopWatch.getTotalTimeMillis());
        return JSON.toJSONString(rootDepartments);
    }

    /**
     * 查询部门和其所有子节点部门
     * @param list 要递归的集合
     * @param id id指定递归的部门的id
     * @return String树形结构
     * @throws Exception
     * @description: 使用嵌套for循环 + 递归，遍历list中的数据，将数据与list中的数据比对，将比对结果加入到list中
     * */
    public String  recursionDepartment2(List<Department> list,Integer id) throws InterruptedException {
        StopWatch stopWatch=new StopWatch();
        log.warn("Route=>DepartmentService method=recursionDepartment2 >>> 要递归的数据list为：{}",list);
        if(CollectionUtils.isEmpty(list)){
            log.error("lRoute=>DepartmentService method=recursionDepartment2 >>> 要递归的数据list集合为空！");
            return "[]";
        }
        stopWatch.start("recursionDepartment2");
        // 2层嵌套循环，即取出list中每一条数据，该数据再和list中每一条数据比对
        for(Department department : list){
            ArrayList<Department> list1 = new ArrayList<>();
            for(Department department1 : list){
                if(department1.getParentId()==department.getId()){//如果department1有父节点，把department1挂到其父节department点下
                    list1.add(department1);//department的子节点集合
                }
                //递归子节点department1（即如果department1也有子节点，把子节点挂到其父节点department1下）
                //recursionDepartment1(list1);
                //每次递归都重排序一次
                //list1.stream().sorted(Comparator.comparing(Department::getId));
            }
            if(!CollectionUtils.isEmpty(list1)){
                //递归子节点department1（即如果department1也有子节点，把子节点挂到其父节点department1下）;但我发现递归也可以不写，效果还是一样得
                recursionDepartment2(list1,id);
            }
            department.setChildren(list1);
        }
        // 获取所有根节点（即没有父节点的部门），因为上面2层for循环已经把有父节点的数据挂到其父节点下，所有根节点不止根节点，还有其所有的子节点（包括子节点的子节点）
        List<Department> rootDepartments=null;
        if(id==null){
            log.info("Route=>DepartmentService method=recursionDepartment2 >>> 查询所有部门的树形结构");
            rootDepartments  = list.stream().filter(department -> department.getParentId() == 0)
                    .sorted(Comparator.comparing(Department::getId))//树结构根据id排序（默认升序）
                    .collect(Collectors.toList());
        }else{
            log.info("Route=>DepartmentService method=recursionDepartment2 >>> 查询指定部门及其子节点部门的树形结构");
            rootDepartments  = list.stream().filter(department -> department.getId() == id)
                    .sorted(Comparator.comparing(Department::getId).reversed())//树结构根据id排序（降序）
                    .collect(Collectors.toList());
        }
        Thread.sleep(1100);
        stopWatch.stop();
        System.out.println("本方法耗时：" + stopWatch.getLastTaskTimeMillis());
        System.out.println("总耗时：" + stopWatch.getTotalTimeMillis());
        return JSON.toJSONString(rootDepartments);
    }

}